/*
 * This file is part of the quickTools support library, dubbed "LucasCode"
 *
 * Copyright (C) 2005-2008 Lucas Romero
 *
 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Etier.IconHelper;
using System.IO;
using ICSharpCode.SharpZipLib;
using ICSharpCode.SharpZipLib.Zip;
using System.Collections.Specialized;
using System.Reflection;
using System.Xml;

namespace AutoUpdateGenerator
{
    public partial class Form1 : Form
    {
        IconListManager IconManager;
        public Form1()
        {
            InitializeComponent();
            IconManager = new IconListManager(SmallIcons, IconReader.IconSize.Small);
            SmallIcons.Images.Add(IconReader.GetFolderIcon(IconReader.IconSize.Small, IconReader.FolderType.Open));

            comboPath.Text = Properties.Settings.Default.LastUsedFolder;
            browseDir.SelectedPath = Properties.Settings.Default.LastUsedFolder;
            ScanDir(comboPath.Text);
        }

        private void bBrowse_Click(object sender, EventArgs e)
        {
            if(browseDir.ShowDialog() == DialogResult.OK)
            {
                comboPath.Text = browseDir.SelectedPath;
                Properties.Settings.Default.LastUsedFolder = comboPath.Text;
                ScanDir(comboPath.Text);
            }
        }
        private void ScanDir(string path)
        {
            DirectoryInfo d = new DirectoryInfo(path);
            FileTree.Nodes.Clear();
            FileTree.BeginUpdate();
            FillNode(FileTree.Nodes, d);
            FileTree.EndUpdate();


            string updfile = Path.Combine(path, "remoteupdate.xml");
            if(File.Exists(updfile))
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(updfile);
                XmlNode n = doc.SelectSingleNode("UpdateInformation/Mirrors");
                MirrorList.Items.Clear();
                foreach (XmlNode n2 in n.ChildNodes)
                {
                    MirrorList.Items.Add(n2.Attributes["Url"].Value);
                }
            }
        }

        private void FillNode(TreeNodeCollection tn, DirectoryInfo d)
        {
            TreeNode t;
            Assembly asm;
            foreach (DirectoryInfo d2 in d.GetDirectories())
            {
                t = tn.Add("", d2.Name, 0);
                FillNode(t.Nodes, d2);
            }
            foreach (FileInfo f in d.GetFiles())
            {

                t = tn.Add("", f.Name);
                t.Tag = f.FullName;
                string ext = f.Extension.ToLower();
                if (ext == ".exe" || ext == ".ico")
                {
                    t.ImageIndex = SmallIcons.Images.Count;
                    SmallIcons.Images.Add(IconReader.GetFileIcon(f.FullName, IconReader.IconSize.Small, false));
                }
                else
                    t.ImageIndex = IconManager.AddFileIcon(f.FullName);

                if (ext == ".exe" || ext == ".dll" || ext == ".config" || ext == ".ico")
                {
                    t.Checked = true;
                    if (f.Name.EndsWith(".exe.config") && d.FullName == comboPath.Text)
                    {
                        tAppExe.Text = Path.GetFileNameWithoutExtension(f.Name);
                        tAppName.Text = Path.GetFileNameWithoutExtension(tAppExe.Text);
                        asm = Assembly.LoadFrom(Path.Combine(comboPath.Text, Path.GetFileNameWithoutExtension(f.FullName)));
                        tAppVer.Text = asm.GetName().Version.ToString();

                    }
                    else if(ext == ".dll" || ext == ".exe")
                    {
                        asm = Assembly.LoadFrom(f.FullName);
                        t.Text += "  (" + asm.GetName().Version.ToString() + ")";
                    }
                    while (t.Parent != null && !t.Parent.IsExpanded)
                    {
                        t.Parent.Expand();
                        t = t.Parent;
                    }
                }
                
            }
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            Properties.Settings.Default.Save();
        }

        XmlAttribute CreateAttr(XmlDocument d, string name, string value)
        {
            XmlAttribute a = d.CreateAttribute(name);
            a.Value = value;
            return a;
        }
        XmlAttribute AddAttr(XmlElement el, string name, string value)
        {
            return el.Attributes.Append(CreateAttr(el.OwnerDocument, name, value));
        }
        XmlElement AddElem(XmlElement el, string name)
        {
            XmlElement elem;
            el.AppendChild(elem = el.OwnerDocument.CreateElement(name));
            return elem;
        }

        private void bCreateUpdate_Click(object sender, EventArgs e)
        {
            string zipfile = Path.Combine(comboPath.Text, tAppName.Text) + "-" + tAppVer.Text + ".zip";
            FileStream f = new FileStream(zipfile,FileMode.Create,FileAccess.Write,FileShare.Read);
            ZipOutputStream z = new ZipOutputStream(f);
            z.SetLevel(9);

            FileStream fin;
            StringCollection c = new StringCollection();
            getCheckedFiles(FileTree.Nodes, ref c);

            string msg = String.Empty;
            foreach(string s in c)
            {
                msg += s.Replace(comboPath.Text + Path.DirectorySeparatorChar, "") + Environment.NewLine;
                ZipEntry entry = new ZipEntry(s.Replace(comboPath.Text + Path.DirectorySeparatorChar, "")/*.Replace("\\","/")*/);
                z.PutNextEntry(entry);
                fin = new FileStream(s, FileMode.Open, FileAccess.Read, FileShare.Read);
                byte[] buf = new byte[fin.Length];
                fin.Read(buf, 0, buf.Length);
                z.Write(buf, 0, buf.Length);
                fin.Close();
            }
            z.Finish();
            z.Close();

            XmlDocument d = new XmlDocument();
            XmlNode n;
            XmlElement el, root, mirrors;
            XmlAttribute a;
            /* init */
            d.AppendChild(d.CreateXmlDeclaration("1.0", String.Empty, String.Empty));
            d.AppendChild(d.CreateComment("AutoUpdater Information File"));

            /* create root node */
            d.AppendChild(root = d.CreateElement("UpdateInformation"));

            mirrors = AddElem(root, "Mirrors");
            foreach(ListViewItem i in MirrorList.Items)
            {
                mirrors.AppendChild(el = d.CreateElement("Mirror"));
                //AddAttr(el, "Name", "Mirror");
                AddAttr(el, "Url", i.Text);
            }

            //d.AppendChild(n = d.CreateNode(XmlNodeType.Element, "programs", ""));
            el = AddElem(root, "Program");
            AddAttr(el, "Name", tAppName.Text);
            AddAttr(el, "RecentVersion", tAppVer.Text);
            AddAttr(el, "UpdateFile", Path.GetFileName(zipfile));
            d.Save(Path.Combine(comboPath.Text, "remoteupdate.xml"));

            MessageBox.Show(msg);
        }

        void getCheckedFiles(TreeNodeCollection n, ref StringCollection c)
        {
            foreach(TreeNode node in n)
            {
                if (node.GetNodeCount(false) > 0)
                    getCheckedFiles(node.Nodes, ref c);
                if (node.Checked)
                    c.Add((string)node.Tag);

            }
        }

        private void bRefresh_Click(object sender, EventArgs e)
        {
            ScanDir(comboPath.Text);
        }

        private void bAddMirror_Click(object sender, EventArgs e)
        {
            MirrorList.Items.Add("http://my.server.com");
        }

        private void bRemoveMirror_Click(object sender, EventArgs e)
        {
            while (MirrorList.SelectedItems.Count > 0)
                MirrorList.SelectedItems[0].Remove();
        }
    }
}